/**
 *  ------------- 公共模块的方法 --------------
 */

let classtype = {};	
// Populate the classtype map
"Boolean Number String Function Array Date RegExp Object".split(" ").forEach((name, i) => {
	classtype["[object " + name + "]"] = name.toLowerCase();
});

/**
 * [UI ]  定义和基础方法
 */
let UI = {
	extend: function() {
		var options, name, src, copy, copyIsArray, clone,
			target = arguments[0] || {},
			i = 1,
			length = arguments.length,
			deep = false;

		// Handle a deep copy situation
		if ( typeof target === "boolean" ) {
			deep = target;
			// Skip the boolean and the target
			target = arguments[ i ] || {};
			i++;
		}

		// Handle case when target is a string or something (possible in deep copy)
		if ( typeof target !== "object" && !this.isFunction(target) ) {
			target = {};
		}

		// Extend jQuery itself if only one argument is passed
		if ( i === length ) {
			target = this;
			i--;
		}

		for ( ; i < length; i++ ) {
			// Only deal with non-null/undefined values
			if ( (options = arguments[ i ]) != null ) {
				// Extend the base object
				for ( name in options ) {
					src = target[ name ];
					copy = options[ name ];

					// Prevent never-ending loop
					if ( target === copy ) {
						continue;
					}

					// Recurse if we're merging plain objects or arrays
					if ( deep && copy && ( this.isPlainObject(copy) || (copyIsArray = this.isArray(copy)) ) ) {
						if ( copyIsArray ) {
							copyIsArray = false;
							clone = src && this.isArray(src) ? src : [];

						} else {
							clone = src && this.isPlainObject(src) ? src : {};
						}

						// Never move original objects, clone them
						target[ name ] = this.extend( deep, clone, copy );

					// Don't bring in undefined values
					} else if ( copy !== undefined ) {
						target[ name ] = copy;
					}
				}
			}
		}

		// Return the modified object
		return target;
	},
	type: function(obj) {
		return obj == null ? String(obj) : (classtype[Object.prototype.toString.call(obj)] || "object");
	},

	isFunction: function( obj ) {
		return this.type(obj) === "function";
	},

	isArray: Array.isArray,

	isWindow: function( obj ) {
		return obj != null && obj === obj.window;
	},

	isNumeric: function( obj ) {
		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
		// subtraction forces infinities to NaN
		// adding 1 corrects loss of precision from parseFloat (#15100)
		return !this.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
	},

	isPlainObject: function( obj ) {
		// Not plain objects:
		// - Any object or value whose internal [[Class]] property is not "[object Object]"
		// - DOM nodes
		// - window
		if ( this.type( obj ) !== "object" || obj.nodeType || this.isWindow( obj ) ) {
			return false;
		}

		if ( obj.constructor &&
				!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
			return false;
		}

		// If the function hasn't returned already, we're confident that
		// |obj| is a plain object, created by {} or constructed with new Object
		return true;
	},

	isEmptyObject: function( obj ) {
		var name;
		for ( name in obj ) {
			return false;
		}
		return true;
	},

};

/** 
 * [logger  ]
 */
UI.extend(UI, (() => {

	let chalk = require('chalk');
	let log = function(t, ...param) {
		console.log(chalk[t].bold(chalk.gray.bgWhite('Tip:'),...param));
	}
	return {
		log(...param){
			log('blue', ...param);
			return this;
		},
		error(...param){
			log('red', ...param);
		},
		success(...param){
			log('green', ...param);
		},
		def(...param){
			log('black', ...param);
		}
	};

})());
/**
 * [other]
 */
UI.extend(UI, (() => {
	var crypto = require('crypto');
	return {
		md5(val){
	        var md5 = crypto.createHash('md5');  
	        val = val.trim();
	        md5.update(val);  
	        return md5.digest('hex');  
	    },

	    getMongId(val){
	        val = val ? val.toString() : 0; 
	        if(val.length != 24) val = "000000000000000000000000";
	        return  require('mongoose').Types.ObjectId(val);
	    }

	};

	})());

export default UI;
